﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Web;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Extensions.Primitives;
using Microsoft.AspNetCore.Http;

namespace Having.Site.Base
{
    /// <summary>
    /// 常用的基础接口
    /// </summary>
    public partial class BaseMethod
    {
        /// <summary>
        /// 初始化类
        /// </summary>
        /// <param name="obj">实体类</param>
        /// <returns></returns>
        public static object InitClass(object obj)
        {
            PropertyInfo[] pis = obj.GetType().GetProperties();
            foreach (PropertyInfo pi in pis)
            {
                if (pi.PropertyType == typeof(string) || pi.PropertyType == typeof(String))
                {
                    pi.SetValue(obj, "", null);
                    continue;
                }
                if (pi.PropertyType == typeof(int) || pi.PropertyType == typeof(Int16) || pi.PropertyType == typeof(Int32) || pi.PropertyType == typeof(Int64) || pi.PropertyType == typeof(decimal) || pi.PropertyType == typeof(Decimal) || pi.PropertyType == typeof(double) || pi.PropertyType == typeof(Double) || pi.PropertyType == typeof(float))
                {
                    pi.SetValue(obj, Convert.ChangeType(0, pi.PropertyType), null);
                    continue;
                }
                if (pi.PropertyType == typeof(DateTime))
                {
                    pi.SetValue(obj, DateTime.Now, null);
                    continue;
                }
                if (pi.PropertyType == typeof(bool) || pi.PropertyType == typeof(Boolean))
                {
                    pi.SetValue(obj, false, null);
                    continue;
                }
                if (pi.PropertyType == typeof(Enum))
                {
                    continue;
                }
                pi.SetValue(obj, Activator.CreateInstance(pi.PropertyType), null);
            }
            return obj;
        }

        /// <summary>
        /// 匹配html并去除html标志
        /// </summary>
        /// <param name="str">要匹配的字符串</param>
        /// <returns></returns>
        public static string ReMoveHTML(string str)
        {
            System.Text.RegularExpressions.Regex Regex = new System.Text.RegularExpressions.Regex("<[^>]*>", System.Text.RegularExpressions.RegexOptions.Compiled);
            str = Regex.Replace(str, "");
            return str;
        }

        /// <summary>
        /// unix时间转换为datetime
        /// </summary>
        /// <param name="timeStamp"></param>
        /// <returns></returns>
        public static DateTime UnixTimeToTime(long timeStamp)
        {
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            long lTime = long.Parse(timeStamp.ToString() + "0000000");
            TimeSpan toNow = new TimeSpan(lTime);
            return dtStart.Add(toNow);
        }

        /// <summary>
        /// datetime转换为unix时间
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static long ConvertDateTimeInt(System.DateTime time)
        {
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
            return (long)(time - startTime).TotalSeconds;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T">返回的对象</typeparam>
        /// <param name="data">请求的数据</param>
        /// <param name="url">提交的url</param>
        /// <param name="encod">使用的编码</param>
        /// <param name="Ti">请求回来数据执行的方法(第一个是body内存流,第二个是string是ContentType,头部文件说明),第3个是头部信息集合</param>
        /// <param name="ContentType">请求的方式</param>
        /// <param name="CertPath">证书的路径</param>
        /// <param name="CertKey">证书的密钥</param>
        /// <param name="headerdic">附加的头部信息</param>
        /// <returns></returns>
        public static T WebRequestPostBase<T> (string data, string url, Encoding encod, Func<Stream,string,WebHeaderCollection,  T> Ti, int Timeout= 60000, string ContentType = "", string CertPath = "", string CertKey = "", Dictionary<string, string> headerdic = null)
        {
            comm.HttpOffer offer = new comm.HttpOffer(url, data, encod, Timeout, ContentType, headerdic, CertPath, CertKey);
            return WebRequestPostBase(offer, Ti);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T">返回的对象</typeparam>
        /// <param name="offer">请求的对象</param>
        /// <param name="Ti">请求回来数据执行的方法(第一个是body内存流,第二个是string是ContentType,头部文件说明),第3个是头部信息集合</param>
        /// <returns></returns>
        public static T WebRequestPostBase<T>(comm.HttpOffer offer, Func<Stream, string, WebHeaderCollection, T> Ti)
        {
            T Geturl;
            var uri = new Uri(offer.Url);
            if (uri.Scheme.ToLower() == "https")
            {
                try
                {
                    //表示使用ssl证书
                    ServicePointManager.Expect100Continue = true;
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
                }
                catch
                { }
            }
            HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(offer.Url);
            Request.Method = "post";
            Request.KeepAlive = false;
            Request.AllowAutoRedirect = true;
            Request.Timeout = offer.Timeout;
            if (offer.HeaderDic != null && offer.HeaderDic.Count > 0)
            {
                foreach (var pi in offer.HeaderDic)
                {
                    if (pi.Key != "Accept")
                    {
                        Request.Headers.Add(pi.Key, pi.Value);
                    }
                    else
                    {
                        Request.Accept = offer.HeaderDic["Accept"];
                    }
                }
            }

            if (string.IsNullOrWhiteSpace(offer.ContentType))
            {
                Request.ContentType = "application/x-www-form-urlencoded";
            }
            else
            {
                Request.ContentType = offer.ContentType;
            }
            byte[] bs = offer.Encod.GetBytes(offer.Data);
            Request.ContentLength = bs.Length;
            Request.Headers.Add("Charset", offer.Encod.WebName);

            if (!string.IsNullOrWhiteSpace(offer.CertPath) && !string.IsNullOrWhiteSpace(offer.CertKey))
            {
                X509Certificate2 cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(offer.CertPath, offer.CertKey, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.PersistKeySet); //设置证书
                ServicePointManager.ServerCertificateValidationCallback += CheckValidationResult;
                Request.ProtocolVersion = HttpVersion.Version11;
                Request.ClientCertificates.Add(cert);//添加证书到请求中
            }
            using (Stream reqStream = Request.GetRequestStream())
            {
                reqStream.Write(bs, 0, bs.Length);
            }
            using (WebResponse wr = Request.GetResponse())
            {
                Geturl = Ti(wr.GetResponseStream(), wr.ContentType, wr.Headers);
                wr.Close();
            }
            Request.Abort();
            return Geturl;
        }

        /// <summary>
        /// 使用Post提交数据,使用证书
        /// </summary>
        /// <param name="data">用"与"组合的参数值 </param>
        /// <param name="url"></param>
        /// <param name="encod"></param>
        /// <param name="ContentType"></param>
        /// <param name="CertPath">证书的路径，名字</param>
        /// <param name="CertKey">访问证书的密码</param>
        /// <returns></returns>
        public static string WebRequestPost(string data, string url, Encoding encod=null, int Timeout = 60000, string ContentType="", string CertPath="", string CertKey="", Dictionary<string, string> headerdic=null)
        {
            encod = encod ?? Encoding.UTF8 ;
            string Geturl = null;
            Geturl= WebRequestPostBase(data, url, encod, 
                delegate(Stream stm,string backContentType,WebHeaderCollection headers) {
                StreamReader st = new StreamReader(stm, encod);
                var str = st.ReadToEnd();
                st.Close();
                return str;
            }, Timeout, ContentType, CertPath, CertKey, headerdic);
            return Geturl;
        }



        public static string WebRequestPost(string data, string url, string encod, int Timeout = 60000, string ContentType="", string CertPath="", string CertKey="")
        {
            return WebRequestPost(data, url, Encoding.GetEncoding(encod), Timeout, ContentType, CertPath, CertKey);
        }

        /// <summary>
        /// 使用Post提交数据
        /// </summary>
        /// <param name="data">用"与"组合的参数值</param>
        /// <param name="url"></param>
        /// <param name="encod"></param>
        /// <param name="headerdic">头部组合</param>
        /// <returns></returns>
        public static string WebRequestPost(string data, string url,  Encoding encod, string ContentType, Dictionary<string, string> headerdic, int Timeout = 60000)
        {
            return WebRequestPost(data, url, encod, Timeout, ContentType, "", "", headerdic);
        }

        public static string WebRequestPost(string data, string url, string encod, string ContentType, Dictionary<string, string> headerdic, int Timeout = 60000)
        {
            return WebRequestPost(data, url, Encoding.GetEncoding(encod), Timeout, ContentType,"","", headerdic);
        }
        /// <summary>
        /// 使用get去获取数据
        /// </summary>
        /// <typeparam name="T">返回的类型</typeparam>
        /// <param name="url"></param>
        /// <param name="Ti">请求回来数据执行的方法(第一个是body内存流,第二个是string是ContentType,头部文件说明),第3个是头部信息集合</param>
        /// <param name="headdic">头部附加请求的方式</param>
        /// <returns></returns>
        public static T WebRequestGetBase<T>(string url, Func<Stream, string, WebHeaderCollection, T> Ti, int Timeout = 60000, Dictionary<string, string> headdic=null)
        {
            T Geturl=default(T);
            var uri = new Uri(url);
            if (uri.Scheme.ToLower()== "https")
            {
                try
                {
                    //表示使用ssl证书
                    ServicePointManager.Expect100Continue = true;
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
                }
                catch
                { }
            }
            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
            req.Method = "GET";
            req.KeepAlive = true;
            req.Timeout = Timeout;
            req.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
            req.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.108 Safari/537.36";
            if (headdic != null && headdic.Count > 0)
            {
                if (headdic.ContainsKey("Host") && !string.IsNullOrEmpty(headdic["Host"]))
                {
                    req.Host = headdic["Host"];
                }
                foreach (var dic in headdic)
                {
                    try
                    {
                        req.Headers.Add(dic.Key, dic.Value);
                    }
                    catch
                    { }
                }
            }
            try
            {
                using (WebResponse wr = req.GetResponse())
                {
                    Geturl = Ti(wr.GetResponseStream(), wr.ContentType, wr.Headers);
                    wr.Close();
                }
            }
            catch
            {
                
            }
            req.Abort();
            return Geturl;
        }
        public static string WebRequestGet(string url, Encoding encod, int Timeout = 60000, Dictionary<string,string> headdic=null)
        {
            return WebRequestGetBase<string>(url, delegate (Stream stm, string backContentType, WebHeaderCollection headers)
            {
                StreamReader st = new StreamReader(stm, encod);
                var str = st.ReadToEnd();
                st.Close();
                return str;
            },Timeout,headdic);
        }

        public static string WebRequestGet(string url, string encod, int Timeout = 60000, Dictionary<string, string> headdic=null)
        {
            return WebRequestGet(url, Encoding.GetEncoding(encod),Timeout, headdic);
        }



        /// <summary>
        /// 文件上传
        /// </summary>
        /// <param name="url">要上传的地址</param>
        /// <param name="filename">文件的路径</param>
        /// <returns></returns>
        public static string UploadFileByWebClient(string url, string filename)
        {
            try
            {
                string[] ps = filename.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
                WebClient wc = new WebClient();
                FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
                long IfSize = fs.Length;
                wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded;");
                byte[] bs = wc.UploadFile(url, "Post", filename);
                fs.Dispose();
                wc.Dispose();
                return Encoding.UTF8.GetString(bs);
            }
            catch
            {
                return "";
            }
        }

        /// <summary>
        /// 把类转换为集合
        /// </summary>
        /// <param name="c"></param>
        /// <param name="code">参数，不是值（0,不变，1，全部小写，2，全部大写）</param>
        /// <param name="iskeep">是否保留空值</param>
        /// <returns></returns>
        public static SortedDictionary<string, string> MakeToDictionary(object c, int code=0,bool iskeep=false)
        {
            PropertyInfo[] pis = c.GetType().GetProperties();
            SortedDictionary<string, string> dic = new SortedDictionary<string, string>();
            foreach (PropertyInfo pi in pis)
            {
                string n = pi.Name;
                switch (code)
                {
                    case 1:
                        n = n.ToLower();
                        break;
                    case 2:
                        n = n.ToUpper();
                        break;
                    default:
                        break;
                }
                if (pi.GetValue(c, null) != null)
                {
                    string p = pi.GetValue(c, null).ToString();
                    if (iskeep)
                    {
                        if (!string.IsNullOrEmpty(p))
                        {
                            dic.Add(n, p);
                        }
                    }
                    else
                    {
                        if (!string.IsNullOrWhiteSpace(p))
                        {
                            dic.Add(n, p);
                        }
                    }
                }
                else
                {
                    continue;
                }
            }
            return dic;
        }

        /// <summary>
        /// 把类转换为集合
        /// </summary>
        /// <param name="c">实体类</param>
        /// <param name="code">参数，不是值（0,不变，1，全部小写，2，全部大写）</param>
        /// <param name="iskeep">是否保留空值或者null（true是保留）</param>
        /// <returns></returns>
        public static Dictionary<string, object> ClassToDictionary(object c, int code = 0, bool iskeep = true)
        {
            PropertyInfo[] pis = c.GetType().GetProperties();
            Dictionary<string, object> dic = new Dictionary<string, object>();
            foreach (PropertyInfo pi in pis)
            {
                string n = pi.Name;
                switch (code)
                {
                    case 1:
                        n = n.ToLower();
                        break;
                    case 2:
                        n = n.ToUpper();
                        break;
                    default:
                        break;
                }

                if (!iskeep)
                {
                    if (pi.GetValue(c, null) != null)
                    {
                        object p = pi.GetValue(c, null);
                        if (pi.PropertyType == typeof(string) || pi.PropertyType == typeof(String))
                        {
                            if (p!=null && !string.IsNullOrWhiteSpace(p.ToString()))
                            {
                                dic.Add(n, p);
                            }
                        }
                        else
                        {
                            dic.Add(n, p);
                        }
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    dic.Add(n, pi.GetValue(c, null));
                }
            }
            return dic;
        }


        /// <summary>
        /// 把集合转换为url参数
        /// </summary>
        /// <param name="dic">集合</param>
        /// <param name="IsEncode">是否需要编码，true表示需要编码</param>
        /// <param name="charset">编码的类型（GBK,UTF-8），可以为NUll(默认编码)</param>
        /// <param name="code">参数，不是值（0,不变，1，全部小写，2，全部大写）</param>
        /// <param name="datacode">值（0,不变，1，全部小写，2，全部大写）</param>
        /// <returns></returns>
        public static string MakeUrl(SortedDictionary<string, string> dic, bool IsEncode=false, string charset="UTF-8", int code=0,int datacode=0)
        {
            string s = "";
            foreach (KeyValuePair<string, string> pi in dic)
            {
                string n = pi.Key;
                switch (code)
                {
                    case 1:
                        n = n.ToLower();
                        break;
                    case 2:
                        n = n.ToUpper();
                        break;
                    default:
                        break;
                }
                var val = (!IsEncode ? pi.Value : ((string.IsNullOrEmpty(charset) || charset == "") ? HttpUtility.UrlEncode(pi.Value) : HttpUtility.UrlEncode(pi.Value, Encoding.GetEncoding(charset))));
                var newval = "";
                switch (datacode)
                {
                    case 0:
                        newval = val;
                        break;
                    case 1:
                        newval = val.ToLower();
                        break;
                    case 2:
                        newval = val.ToUpper();
                        break;
                }
                s += "&" + n + "=" + newval;
            }
            if (s.Length > 0)
            {
                s = s.Substring(1);//去掉第一个“&”；
            }
            return s;
        }

        /// <summary>
        /// 生成签名
        /// </summary>
        /// <param name="str">要签名的字符串</param>
        /// <param name="typeName">MD5/SHA1</param>
        /// <returns></returns>
        public static string Sign(string str, string typeName, string encode)
        {
            string sign = "";
            switch (typeName.ToUpper())
            {
                case "MD5":
                    sign = Having.Site.Encrypt.Cryptography.MD5(str, ((string.IsNullOrEmpty(encode) || encode == "") ? Encoding.Default : Encoding.GetEncoding(encode)));
                    break;
                case "SHA1":
                    sign = Having.Site.Encrypt.Cryptography.SHA1(str, ((string.IsNullOrEmpty(encode) || encode == "") ? Encoding.Default : Encoding.GetEncoding(encode)));
                    break;
                case "SHA256":
                    sign = Having.Site.Encrypt.Cryptography.SHA256(str, ((string.IsNullOrEmpty(encode) || encode == "") ? Encoding.Default : Encoding.GetEncoding(encode)));
                    break;
                default:
                    break;
            }
            return sign;
        }

        /// <summary>
        /// 文件下载,得到byte[]
        /// </summary>
        /// <param name="url"></param>
        /// <param name="filetypes">文件的类型，例如 jpg</param>
        /// <returns></returns>
        public static byte[] DownloadFileByWebClient(string url, out string filetypes)
        {
            filetypes = "";
            WebClient wc = new WebClient();
            var sk= wc.DownloadData(url);
            string[] s = wc.ResponseHeaders["Content-Disposition"].Split(new char[] { '"', '.' }, StringSplitOptions.RemoveEmptyEntries);
            filetypes = s[s.Length - 1];
            return sk;
        }


        /// <summary>
        /// 表示总是接受证书
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="certificate"></param>
        /// <param name="chain"></param>
        /// <param name="errors"></param>
        /// <returns></returns>
        static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {   // 总是接受  
            return true;
        }
        /// <summary>
        /// 判断是否是IP地址格式
        /// </summary>
        /// <param name="str1"></param>
        /// <returns></returns>
        public static bool IsIPAddress(string str1)
        {
            var ist = false;
            IPAddress adr;
            ist= IPAddress.TryParse(str1, out adr);
            return ist;
        }

        /// <summary>
        /// 把A对象的属性对应的值赋值到B相同的属性值上
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        public static void Copy(object a, object b)
        {
            var pis = a.GetType().GetProperties();
            var bpis=b.GetType().GetProperties();
            foreach (PropertyInfo pi in pis)
            {
                var name = pi.Name;
                b.GetType().GetProperty(name).SetValue(b, pi.GetValue(a,null));
            }
        }
        /// <summary>
        /// 把对象Copy到另外类型的对象去
        /// </summary>
        /// <typeparam name="T">新对象的类型</typeparam>
        /// <param name="ev">要被复制的对象</param>
        /// <returns></returns>
        public static T CopyTo<T>(dynamic ev) where T:class,new()
        {
            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(Newtonsoft.Json.JsonConvert.SerializeObject(ev));
        }
        /// <summary>
        /// 把对象Copy到另外类型的对象去
        /// </summary>
        /// <param name="ev">要被复制的对象</param>
        /// <param name="T">接受复制的对象</param>
        /// <returns></returns>
        public static object CopyTo(dynamic ev,Type T)
        {
            return Newtonsoft.Json.JsonConvert.DeserializeObject(Newtonsoft.Json.JsonConvert.SerializeObject(ev),T);
        }

        public static void SetTo(object obj, Newtonsoft.Json.Linq.JToken jt,string[] exto=null) {
            var pis = obj.GetType().GetProperties();
            foreach (PropertyInfo pi in pis)
            {
                if (jt[pi.Name] != null)
                {
                    try
                    {
                        var name = pi.Name;
                        if (exto != null && !exto.Contains(pi.Name))
                        {
                            pi.SetValue(obj, Convert.ChangeType(jt[pi.Name], pi.PropertyType));
                        }
                    }
                    catch { }
                }
            }
        }

        /// <summary>
        /// NameValueCollection 转为字典型
        /// </summary>
        /// <param name="nvc"></param>
        /// <returns></returns>
        public static Dictionary<string, string> NvcToDictionary(System.Collections.Specialized.NameValueCollection nvc)
        {
            var result = new Dictionary<string, string>();
            foreach (string key in nvc.Keys)
            {
                result.Add(key, nvc[key]);
            }

            return result;
        }

        public static SortedDictionary<string, string> NvcToSortedDictionary(System.Collections.Specialized.NameValueCollection nvc)
        {
            var result = new SortedDictionary<string, string>();
            foreach (string key in nvc.Keys)
            {
                result.Add(key, nvc[key]);
            }

            return result;
        }

        /// <summary>
        /// IForm转换为SortedDictionary
        /// </summary>
        /// <param name="nvc"></param>
        /// <returns></returns>
        public static SortedDictionary<string, string> NvcToSortedDictionary(IEnumerable<KeyValuePair<string, StringValues>> nvc)
        {
            var result = new SortedDictionary<string, string>();
            foreach (var item in nvc)
            {
                result.Add(item.Key, item.Value.ToString());
            }

            return result;
        }

        /// <summary>
        /// 根据算法改变字符串的大小写
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string StrEncode(string s)
        {
            var ret = "";
            if (s.Length > 0)
            {
                for (var i = 0; i < s.ToLower().Length; i++)
                {
                    if ((i + (int)s[i]+(i== s.Length-1?0: (int)s[i+1])) % 16 > 8)
                    {
                        ret += s[i].ToString().ToUpper();
                    }
                    else
                    {
                        ret += s[i].ToString().ToLower();
                    }
                }
            }
            else
            {
                ret = s;
            }
            return ret;
        }
        /// <summary>
        /// URL编码
        /// </summary>
        /// <param name="url"></param>
        /// <param name="e">编码</param>
        /// <returns></returns>
        public static string UrlEncode(string url,Encoding e=null)
        {
            if (e == null)
            {
                e = Encoding.UTF8;
            }
            return HttpUtility.UrlEncode(url,e);
        }

        /// <summary>
        /// Url解码
        /// </summary>
        /// <param name="url"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        public static string UrlDecode(string url, Encoding e = null)
        {
            if (e == null)
            {
                e = Encoding.UTF8;
            }
            return HttpUtility.UrlDecode(url,e);
        }

        /// <summary>
        /// base64转16机制的hex
        /// </summary>
        /// <param name="base64str"></param>
        /// <returns></returns>
        public static string Base64ToHEX(string base64str)
        {
            var p= Convert.FromBase64String(base64str);
            var pv= string.Join("", p.Select(b => b.ToString("X2")).ToArray());
            return pv;
        }

        /// <summary>
        /// 16进制的hex转 base64
        /// </summary>
        /// <param name="HEXstr"></param>
        /// <returns></returns>
        public static string HEXToBase64(string HEXstr)
        {
            byte[] inputByteArray = new byte[HEXstr.Length / 2];
            for (int x = 0; x < HEXstr.Length / 2; x++)
            {
                int i = (Convert.ToInt32(HEXstr.Substring(x * 2, 2), 16));
                inputByteArray[x] = (byte)i;
            }
            return Convert.ToBase64String(inputByteArray);
        }


        /// <summary>
        /// 获取当前请求完整的Url地址
        /// </summary>
        /// <returns></returns>
        public static string GetCompleteUrl(HttpRequest Request)
        {
            return new StringBuilder()
                 .Append(Request.Scheme)
                 .Append("://")
                 .Append(Request.Host)
                 .Append(Request.PathBase)
                 .Append(Request.Path)
                 .Append(Request.QueryString)
                 .ToString();
        }

    }
}
